In the context of computer system design, drivers are software components that expose hardware capabilities to the operating system, so that the operating system may in turn expose those capabilities to applications. Typically the operating system interacts with a driver through a Device Driver Interface (“DDI”), a carefully defined protocol that enables the operating system to load the driver, inquire about the capabilities provided by the hardware, and make those capabilities available to applications.
The software interfaces provided to applications by the operating system are known as Application Programming Interfaces (“APIs”). The APIs provided by the operating system provide applications with software abstractions that may or may not closely resemble the characteristics of the underlying hardware. An example of a dramatic departure from the underlying hardware is the directory/file software abstraction provided for mass storage. Another software abstraction that does not resemble the underlying hardware is virtual memory, which enables applications to transparently use local hard disk storage as though it were random access memory.
When APIs cause hardware resources to be utilized, the operating system calls the driver through the DDI to make use of those resources. Due to the differences between the software abstractions provided by APIs and the underlying hardware, this translation from API calls to DDI calls can entail significant amounts of logic and code. In the context of this specification, the software between the application-level API and the driver-level DDI is known collectively as the “runtime.”
Application, drivers, etc. are generally written in a high-level language such as C. Such languages have typically been implemented primarily by compilation to native code. In such cases, drivers are written separately from the application and other programs that operate on a system. The application and drivers are then typically linked together either during an installation process or Dynamic Link Library (DLL) when the application is executed. The advantage of such a system is that the compiler can be designed to optimize the code for a particular class of processor (e.g X86). However, the compiler may not optimize the code for a particular microprocessor, e.g., PENTIUM IV versus PENTIUM III. Moreover the compiler does not optimize the code for other system parameters including driver versions and other hardware components or take into account the particular system constraints of the target system. Instead, the application or runtime level system must employ computationally expensive logic to determine such parameters and processor constraints so that the program can be compiled to execute on an entire class of computer systems.
Another common programming paradigm is to compile code at runtime. A Just-In-Time (JIT) compiler is an example of such as system. Other systems that compile at runtime include continuous compilation systems that immediately begin execution in an interpretive state but compile the code over time and continuously optimize the compilation. With just-in-time compilers, as classes are loaded into the virtual machine, the method pointers in the virtual method table are replaced with pointers to the JIT compiler. Then, the first time each method is called, the JIT compiler is invoked to compile the method. The pointer in the virtual method table is then patched to point to the native-code version of the method so that future calls to the method will jump to the native-code. These JIT compiler systems have the advantage of transmitting code to a target machine in an intermediate language (IL) such as JAVA bytecodes, Common Language Runtime (CLR) instructions, and so on. The compiler is designed to convert the IL into instructions executable by the native processor. As a result, the same IL instructions can be sent to computers having different native processors and execute nonetheless on the target processor.
Although such intermediate language compilers compile the intermediate language instructions on the target computer system, they also do not optimize the code for a particular target computer system, including accounting for driver versions and other hardware components